# -*- coding: utf-8 -*- 
import serial
import binascii
 
com=input("输入串口号：")
while com=="":
    com = input("输入串口号：")
pw=input("输入波特率：")#115200
while pw=="":
    pw = input("输入波特率：")  # 115200
ser = serial.Serial("com"+com, int(pw), timeout=0.5)
ser.bytesize = 8  # 字节大小
ser.parity = serial.PARITY_NONE  # 无校验
ser.stopbits = 1  # 停止位
print("已连接端口：" + str(ser.name)+"\n")
 
 
def sst(data, start, end):  # pn532dsc值的转换
    data = data.replace(" ", "")
    list = []
    i = 0
    b = -2
    c = 0
    while len(data) / 2 > i:
        b = b + 2
        c = c + 2
        li = data[b:c]
        list.append(li)
        i = i + 1
    stt = list
    # print(stt)
    shuju = bytes.fromhex(stt[start])[0]
    i = 6
    while i <= end:
        shuju = shuju + bytes.fromhex(stt[i])[0]
        # print(bytes.fromhex(stt[i])[0])
        i = i + 1
    hex_shuju = hex(int(shuju))
    shuju = ("00" + str(hex_shuju))[-2:]
    # print(shuju)
    bin_shuju = bin(int(shuju, 16)).lstrip("0b")
    # print(bin_shuju)
    if len(bin_shuju) == 8:
        bi = ""
        for s in bin_shuju:
            if s == "1":
                # print(1)
                bi = bi + str(0)
            else:
                # print(0)
                bi = bi + str(1)
        # print(bi)
        sr = "1"
        bin_fan = bin(int(bi, 2) + int(sr, 2))[2:]
        bin_hex = hex(int(bin_fan, 2)).lstrip("0x").upper()
        return (bin_hex)
    else:
        bin_shuju = ("00000000" + bin_shuju)[-8:]
        # print(bin_shuju)
        bi = ""
        for s in bin_shuju:
            if s == "1":
                # print(1)
                bi = bi + str(0)
            else:
                # print(0)
                bi = bi + str(1)
        # print(bi)
        sr = "1"
        bin_fan = bin(int(bi, 2) + int(sr, 2))[2:]
        bin_hex = hex(int(bin_fan, 2)).lstrip("0x").upper()
        return (bin_hex)
 
 
def keyboard():  # 用户输入扇区后转换
    key = input("请输入扇区：")
    while key=="":
        key = input("请输入扇区：")
    if key == "0":
        return "00"
    elif key == "1":
        return "04"
    elif key == "2":
        return "08"
    elif key == "3":
        return "0c"
    elif key == "4":
        return "10"
    elif key == "5":
        return "14"
    elif key == "6":
        return "18"
    elif key == "7":
        return "1C"
    elif key == "8":
        return "20"
    elif key == "9":
        return "24"
    elif key == "10":
        return "28"
    elif key == "11":
        return "2C"
    elif key == "12":
        return "30"
    elif key == "13":
        return "34"
    elif key == "14":
        return "38"
    elif key == "15":
        return "3C"
    else:
        print("请输入数字")
 
 
 
def huan():
    da1 = bytes.fromhex("55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff 03 fd d4 14 01 17 00")
    ser.write(da1)
    ss = str(binascii.b2a_hex(ser.read(25)))[2:-1]
    return ser
 
 
def getid():  # 获取卡号
    ser = huan()
    data = bytes.fromhex("00 00 FF 04 FC D4 4A 02 00 E0 00")
    print("获取卡片信息")
    ser.write(data)
    redata_yid = str(binascii.b2a_hex(ser.read(25)))[2:-1]
    if len(redata_yid) == 50:
        # print("数据返回正确：" + redata_yid)
        id = redata_yid[-12:-4]
        print("卡号：" + id)
        return id, ser
 
    else:
        print("数据返回出错:" + redata_yid)
        # print("长度" + str(len(redata_yid)))
        return "0", "0"
 
 
def yanz():  # 验证扇区密码
    id = getid()[0]
    if id[0] != "0":
        global k
        k = keyboard()
        # ya = "00 00 FF 0F F1 D4 40 01 60"+k+"FF FF FF FF FF FF 4E 9C 74 4C b2 00"
        password = input("输入密码12位：")
        while 12!=len(password):
            password=input("请重新输入密码12位：")
        password = password.replace(" ", "")
        yss = "00 00 FF 0F F1 D4 40 01 60" + k + password + id + "b2 00"
        dcs = "00 00 FF 0F F1 D4 40 01 60" + k + password + id + sst(yss, 5, 19) + " 00"
        dcs = dcs.replace(" ", "")
        # print(dcs)
        yanze = bytes.fromhex(dcs)
        ser.write(yanze)
        erok = str(binascii.b2a_hex(ser.read(32)))[2:-1]
        ma = erok[-8:-4]
        if ma == "4100":
            # print(ma)
            print("密码正确")
            readdata()
            return ser
        else:
            print("密码错误\n")
            a = input("回车继续")
    else:
        print("获取失败,请检查卡有没有放好，或按回车重试\n")
        input("回车继续")
 
 
def blokey(block_key):  # 通过扇区获取块号
    blo_k = bin(int(k, 16))
    # ii="1"
    # blo_k=bin(int(blo_k, 2) - int(ii, 2))
    k_hex = bin(int(block_key, 16))
    sun_bl = bin(int(blo_k, 2) + int(k_hex, 2))
    blo_hex = ("000" + hex(int(sun_bl, 2)).lstrip("0x"))[-2:]
    return (blo_hex)
 
 
def readdata():  # 读出块数据
    global block_key
    write=input("0读1写：")
    while 1!=len(write):
        write = input("请重新输入0读1写：")
    if write=="0":
        block_key = input("请输入块号(0-3)：")
        while 1 != len(block_key):
            block_key = input("请重新输入块号(0-3)：")
        blo = blokey(block_key)
        reco = "00 00 ff 05 fb D4 40 01 30 " + blo + "86  00"
        recode = bytes.fromhex("00 00 ff 05 fb D4 40 01 30 " + blo + sst(reco, 5, 9) + " 00")
        ser.write(recode)
        ss = str(binascii.b2a_hex(ser.read(64)))[2:-1]
        if ss[-9:-4] != "54113":
            block_d = ss[-36:-4]
            print("读出数据：" + block_d+"\n")
            input("回车继续")
 
        else:
            print("读取失败\n")
            input("回车继续")
    elif write=="1":
        # print("写")
        writedata()
    else:
        print("请输入有效值")
 
 
def writedata():#写入数据
    block_key = input("请输入块号(0-3)：")
    while 1!=len(block_key):
        block_key = input("请重新输入块号(0-3)：")
    data=input("输入写入数据：")
    while 32!=len(data):
        data = input("32位数据请重新输入数据：")
    blo = blokey(block_key)
    reco = "00 00 ff 15 EB D4 40 01 A0 "+blo+data+" D2 00"
    writecode = bytes.fromhex("00 00 ff 15 EB D4 40 01 A0 "+blo+data+sst(reco,5,25)+" 00")
    ser.write(writecode)
    ss = str(binascii.b2a_hex(ser.read(64)))[2:-1]
    # print(ss[-9:-4])
    if ss[-9:-4] == "54100":
        print("成功写入数据：" + data+"\n")
        input("回车继续")
 
    else:
        print("写入失败")
        input("回车继续")
 
 
while True:
    yanz()
 
ser.close()